// Copyright (C) Microsoft Corporation. All rights reserved.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization ;
using System.IO;
using System.Net;

namespace Microsoft.DDSolutions.TfsAdmin.Tests
{
    public class DomainUser
    {
        private string username;

        private ArrayList listTfsRoles;
        private ArrayList listSpRoles;
        private ArrayList listRsRoles;

        public enum RoleType { TfsRole, SPRole, RSRole };

        public DomainUser()
        {
            listTfsRoles = new ArrayList();
            listSpRoles = new ArrayList();
            listRsRoles = new ArrayList();
        }

        public DomainUser(string nameP)
        {
            listTfsRoles = new ArrayList();
            listSpRoles = new ArrayList();
            listRsRoles = new ArrayList();

            username = nameP;
        }

        /// <summary>
        ///  Name of the user
        /// </summary>
        [XmlAttribute("username")]
        public string UserName
        {
            get
            {
                return username;
            }
            set
            {
                if (String.IsNullOrEmpty(value) == true)
                    throw new ArgumentNullException(TestResource.strUserName);
                username = value;
            }
        }

        /// <summary>
        ///  List of TFS role assigned to the user
        /// </summary>
        [XmlElement("TfsRole")]
        public string[] TfsRoles
        {
            get
            {
                return GetRoles(RoleType.TfsRole);
            }
            set
            {
                if (value == null) return;
                string[] roles = (string[])value;

                SetRoles(RoleType.TfsRole, roles);

            }
        }

        /// <summary>
        ///  List of SharePoint Roles assigned to the user.
        /// </summary>
        [XmlElement("SpRole")]
        public string[] SPRoles
        {
            get
            {
                return GetRoles(RoleType.SPRole);
            }
            set
            {
                if (value == null) return;
                string[] roles = (string[])value;

                SetRoles(RoleType.SPRole, roles);

            }
        }

        /// <summary>
        ///  List of Reporting Services roles assigned to the user.
        /// </summary>
        [XmlElement("RsRole")]
        public string[] RSRoles
        {
            get
            {
                return GetRoles(RoleType.RSRole);
            }
            set
            {
                if (value == null) return;
                string[] roles = (string[])value;

                SetRoles(RoleType.RSRole, roles);

            }
        }

        /// <summary>
        ///   Add the role to respective sub system list of roles.  type specifies to which sub system list it gets added
        /// </summary>
        /// <param name="roleName">Name of the Role</param>
        /// <param name="type">Specifies if the Role is a TFS or SharePoint or RS role</param>
        /// <returns></returns>
        public int AddRole(string roleName, RoleType type)
        {
            if (String.IsNullOrEmpty(roleName) == true)
                throw new ArgumentNullException(TestResource.strRoleName);

            if (type == RoleType.TfsRole)
                return listTfsRoles.Add(roleName);
            else if (type == RoleType.SPRole)
                return listSpRoles.Add(roleName);
            else if (type == RoleType.RSRole)
                return listRsRoles.Add(roleName);
            else
                throw new ArgumentException(TestResource.InvalidRoleTypeMsg, TestResource.strType);
        }

        /// <summary>
        ///  Helper function. Returns the actual internal list of roles given the type which specifies which list
        /// we are interested in.
        /// </summary>
        /// <param name="type">Specifies if its TFS or SharePoint or RS</param>
        /// <returns></returns>
        private string[] GetRoles(RoleType type)
        {
            ArrayList listref = null;

            listref = GetList(type);
    
            string[] roles = new string[listref.Count];
            listref.CopyTo(roles);
            return roles;
        }

        
        /// <summary>
        ///   Set the internal role list. Type specifies which list (TFS or SP or RS)
        /// </summary>
        /// <param name="type">Type specifies which list (TFS or SP or RS)</param>
        /// <param name="roles">List of Roles to be assigned to this user</param>
        private void SetRoles(RoleType type, string[] roles)
        {
            ArrayList listref = null;
            
            listref = GetList(type);

            listref.Clear();
            foreach (string role in roles)
                listref.Add(role);
        }

        private ArrayList GetList(RoleType type)
        {
            ArrayList listref = null;

            if (type == RoleType.TfsRole)
                listref = listTfsRoles;
            else if (type == RoleType.SPRole)
                listref = listSpRoles;
            else if (type == RoleType.RSRole)
                listref = listRsRoles;
            else
                throw new ArgumentException(TestResource.InvalidRoleTypeMsg, TestResource.strType);

            return listref;
        }


    };

    [XmlRootAttribute(Namespace="TestConfig",IsNullable=false)]
    public class TestConfig
    {
        private string serverName;
        private string teamProjectName;
        private ArrayList listDomainUsers;
        private string serverDomain;

        public TestConfig()
        {
            listDomainUsers = new ArrayList();
        }

        /// <summary>
        ///  Name of the TFS server.
        /// </summary>
        [XmlElement(ElementName="Server", IsNullable = false)]
        public string Server
        {
            get
            {
                return serverName;
            }
            set
            {

                if (String.IsNullOrEmpty(value) == true)
                    throw new ArgumentNullException(TestResource.strServer);

                serverName = value;
            }
        }

        /// <summary>
        ///  Domain of the TFS server.
        /// </summary>
        [XmlElement(ElementName = "ServerDomain", IsNullable = false)]
        public string ServerDomain
        {
            get
            {
                return serverDomain;
            }
            set
            {

                if (String.IsNullOrEmpty(value) == true)
                    throw new ArgumentNullException(TestResource.strServerDomain);

                serverDomain = value;
            }
        }

        /// <summary>
        ///  Name of the team project.
        /// </summary>
        [XmlElement(ElementName = "TeamProject", IsNullable = false)]
        public string TeamProject
        {
            get
            {
                return teamProjectName;
            }

            set
            {

                if (String.IsNullOrEmpty(value) == true)
                    throw new ArgumentNullException(TestResource.strTeamProject);

                teamProjectName = value;
            }
        }

       /// <summary>
       ///  List of Domain Users.
       /// </summary>
        [XmlElement("DomainUser")]
        public DomainUser[] DomainUsers
        {
            get
            {
                DomainUser[] users = new DomainUser[listDomainUsers.Count];
                listDomainUsers.CopyTo(users);
                return users;
            }
            set
            {
                if (value == null) return;

                DomainUser[] users = (DomainUser[])value;
                listDomainUsers.Clear();
                foreach (DomainUser user in users)
                    listDomainUsers.Add(user);
            }
        }

        /// <summary>
        ///   Add a domain user object to the internal list.
        /// </summary>
        /// <param name="user">A DomainUser object that represents the actual domain user</param>
        /// <returns></returns>
        public int AddDomainUser(DomainUser user)
        {
            if (user == null)
                throw new ArgumentNullException(TestResource.strUser);

            return listDomainUsers.Add(user);
        }

        /// <summary>
        ///  Helper function that forms a domain\\username string.
        /// </summary>
        /// <param name="user">Name of the user</param>
        /// <returns>The domain username in the format domain\\user</returns>
        public string GetDomainUserName(string user)
        {
            if (String.IsNullOrEmpty(user) == true)
                throw new ArgumentNullException(TestResource.strUser);

            StringBuilder sb = new StringBuilder(serverDomain);
            sb.Append("\\");
            sb.Append(user);
            return sb.ToString();
        }

        /// <summary>
        ///   Deserialize or Load this object member values from an XML file
        /// </summary>
        /// <param name="filePath">Name of the xml file</param>
        /// <returns></returns>
        public static TestConfig Load(string filePath)
        {
            TestConfig retval = null;
            try
            {
                XmlSerializer ser = null;
                using (Stream s = File.OpenRead(filePath))
                {
                    ser = new XmlSerializer(typeof(TestConfig));
                    retval = (TestConfig)ser.Deserialize(s);
                }
            }
            catch (System.IO.FileNotFoundException ex)
            {
                DumpException(ex);
            }
            catch (System.UnauthorizedAccessException ex)
            {
                DumpException(ex);
            }

            return retval;
        }

        /// <summary>
        ///   Serialize this object as an XML file to disk.
        /// </summary>
        /// <param name="filePath">Filename</param>
        public void Save(string filePath)
        {
            try
            {
                using (Stream s = File.OpenWrite(filePath))
                {
                    XmlSerializer ser = new XmlSerializer(typeof(TestConfig));
                    ser.Serialize(s, this);
                }
            }
            catch (System.IO.PathTooLongException ex)
            {
                DumpException(ex);
            }
            catch (System.ArgumentNullException ex)
            {
                DumpException(ex);
            }
            catch (System.UnauthorizedAccessException ex)
            {
                DumpException(ex);
            }

        }

        /// <summary>
        ///  Helper function to display the exception details on the console window needed while running tests.
        /// </summary>
        /// <param name="ex">Instance of an exception</param>
        public static void DumpException(Exception ex)
        {
            if (ex == null)
                throw new ArgumentNullException(TestResource.strEx);

            Console.WriteLine("--------- Outer Exception Data ---------");
            WriteExceptionInfo(ex);
            ex = ex.InnerException;
            if (ex != null)
            {
                Console.WriteLine("--------- Inner Exception Data ---------");
                WriteExceptionInfo(ex.InnerException);
                ex = ex.InnerException;
            }
        }

        /// <summary>
        ///  Helper function to write inner exception details on to the console window during test run.
        /// </summary>
        /// <param name="ex">Instance of an exception</param>
        public static void WriteExceptionInfo(Exception ex)
        {
            if (ex == null)
                throw new ArgumentNullException(TestResource.strEx);

            Console.WriteLine("Message: {0}", ex.Message);
            Console.WriteLine("Exception Type: {0}", ex.GetType().FullName);
            Console.WriteLine("Source: {0}", ex.Source);
            Console.WriteLine("StrackTrace: {0}", ex.StackTrace);
            Console.WriteLine("TargetSite: {0}", ex.TargetSite);
        }


    }
}
